#include "People.h"

// Person 构造函数
Person::Person(
        int& i_id,
        std::string& i_name,
        std::string& i_address,
        std::string& i_phone,
        std::vector<std::string>& i_locations,
        std::vector<Vacci>& i_vaccination,
        NAT& i_nat) {  // Warning for unknown reason, but the program does work
    id = i_id;
    name = std::move(i_name);  // 使用 move() 来避免拷贝构造
    address = std::move(i_address);
    phone = std::move(i_phone);
    locations.assign(i_locations.begin(), i_locations.end());
    vaccination.reserve(3);
    vaccination.assign(i_vaccination.begin(), i_vaccination.end());
    nat = std::move(i_nat);
}

inline State print_person(const Person& person) { // 打印 Person
    using namespace std;
    cout << "姓名：\t" << person.name << endl;
    cout << "住址：\t" << person.address << endl;
    cout << "联系电话：\t" << person.phone << endl;
    cout << "活动轨迹：\t" << endl;
    for (const std::string& iter : person.locations)
        cout << iter << " -> ";
    cout << endl;
    cout << "疫苗接种情况：\t";
    if (person.vaccination.empty())
        cout << "未接种" << endl;
    else {
        cout << "已接种" << person.vaccination.size() << "针" << endl;
        for (int i = 0; i < person.vaccination.size(); i++) {
            cout << "第" << i + 1 << "针：" << endl;
            cout << "\t接种时间\t" << person.vaccination[i].time << endl;
            cout << "\t生产厂家：\t" << person.vaccination[i].producer << endl;
            cout << "\t接种单位\t" << person.vaccination[i].location << endl;
        }
    }
    cout << "核酸检测情况：\t";
    if (person.nat.result == -1)
        cout << "近期无核酸检测结果";
    else {
        cout << person.nat.hour << "小时" << person.nat.GetResult() << endl;
        cout << "\t采样时间\t" << person.nat.time << endl;
    }
    State state(State::OK, "OK");
    return state;
}

//--- People 内置方法定义 ---//
State People::add_person() {
    using namespace std;
    // 基本人员信息
    int id = this->list.back().id + 1;
    string name, address, phone, location;
    cout << "姓名：";
    cin >> name;
    cout << "住址：";
    cin >> address;
    cout << "联系电话：";
    cin >> phone;
    // 所在地
    cout << "当前所在地：";
    cin >> location;
    std::vector<std::string> locations;
    locations.emplace_back(location);
    // 疫苗
    vector<Vacci> vaccination;
    vaccination.reserve(3);
    auto* Int2Char = new string[3];
    Int2Char[0] = "一";
    Int2Char[1] = "二";
    Int2Char[2] = "三";
    int i = 0;
    while (i < 3) {
        cout << "是否已接种第" << Int2Char[i] << "针疫苗（请输入是或否）：";  // 做成下拉列表
        string tmp;
        cin >> tmp;
        if (tmp == "否") break;
        else if (tmp == "是") {
            string v_time, v_producer, v_location;
            cout << "接种时间：";
            cin >> v_time;
            cout << "生产厂家：";
            cin >> v_producer;
            cout << "接种地点：";
            cin >> v_location;
            Vacci vacci{v_time, v_producer, v_location};
            vaccination.emplace_back(vacci);
            i++;
        }
        else {
            cout << "请输入是或否！！！";
            continue;
        }
    }
    delete[] Int2Char;
    // 核酸检测
    int n_hour = 0;
    string n_result_str, n_time;
    NAT nat{};
    while (n_result_str != "无" && n_result_str != "阴性" && n_result_str != "阳性") {
        cout << "核酸检测结果（请输入阴性或阳性或无）：";
        cin >> n_result_str;
        if (n_result_str == "无") {
            NAT tmp{.result = NAT::NoResult};
            nat = tmp;
        }
        else if (n_result_str == "阴性") {
            while (n_hour != 24 && n_hour != 48 && n_hour != 72) {
                cout << "几小时内核酸检测报告（24，48，72）：";
                cin >> n_hour;
                if (n_hour != 24 && n_hour != 48 && n_hour != 72)
                    cout << "请输入24，48，72其中之一的数字！！！";
            }
            cout << "检测时间：";
            cin >> n_time;
            NAT tmp{.result = NAT::Negative, .hour = n_hour, .time = n_time};  // 此初始化方法更直观
            nat = tmp;
        } else if (n_result_str == "阳性") {
            while (n_hour != 24 && n_hour != 48 && n_hour != 72) {
                cout << "几小时内核酸检测报告（24，48，72）：";
                cin >> n_hour;
                if (n_hour != 24 && n_hour != 48 && n_hour != 72)
                    cout << "请输入24，48，72其中之一的数字！！！";
            }
            cout << "检测时间：";
            cin >> n_time;
            NAT tmp{.result = NAT::Positive, .hour = n_hour, .time = n_time};
            nat = tmp;
        }
    }
    Person person(id, name, address, phone, locations, vaccination, nat);
    this->list.emplace_back(person);
    State state(State::OK, "");
    return state;
}

int People::find_base(const std::string& base) {  // 当类型为 std::string 时可调用，包括 name, address, phone
    for (const Person& person : this->list)
        if (person.name == base)
            return person.id;
    return -1;
}  //-> -1 for Not Found

//-- filter 系列函数，通过传入所在地，疫苗接种情况，核酸检测情况，进行筛查 --//
// 所在地 filter
// 若查询到某个人去过 locations 中的任一 location，则入表
// 返回指针避免拷贝构造(?)，记得 delete
std::vector<int>* People::filter_loca(const std::vector<std::string>& locations) {
    auto* PeopleList = new std::vector<int>;
    PeopleList->reserve(this->list.size());  // PeopleList 不可能大于 people
    for (const Person& person : this->list) {
        for (const std::string &p_location: person.locations)
            for (const std::string &location: locations)
                if (p_location == location) {
                    PeopleList->emplace_back(person.id);
                    goto superBreak;
                }
        superBreak:;  // 退出双重循环的 label
    }
    PeopleList->shrink_to_fit();  // 回收多 reserve 的内存
    return PeopleList;
}

std::vector<std::vector<int>>* People::filter_nat_and_vacci(const int mode) {
    /**
     * @param int mode -> 0 for NAT filter, 1 for Vaccination filter
     */
    auto* PeopleList = new std::vector<std::vector<int>>;  // mode+3 种 People, 每个 People 最大为 people.size()
    PeopleList->reserve(mode+3);
    for (std::vector<int>& EachPeople : *(PeopleList))
        EachPeople.reserve(this->list.size());
    for (const Person& person : this->list)
        PeopleList->at(person.vaccination.size()).emplace_back(person.id);  // 似乎用 [] 不能正确访问其中的 People, 且 at() 有越界检查
    for (std::vector<int>& EachPeople : *(PeopleList))  // 回收多 reserve 的内存
        EachPeople.shrink_to_fit();
    return PeopleList;
}
//-- filter 系列函数 --//

//-- update 系列函数 --//
// 可使用 C++11 可变参数模板合并
State People::update_base(const int f_id, std::string& UpdatedInfo, const int mode) {
    /**
     * @param int mode -> mode_name, mode_addr, mode_phone in Person;
     */
    Person& person = this->list.at(f_id);
    if (mode == Person::mode_name)
        person.name = UpdatedInfo;
    else if (mode == Person::mode_addr)
        person.address = UpdatedInfo;
    else if (mode == Person::mode_phone)
        person.phone = UpdatedInfo;
    else {
        State state(State::Error, "Invalid Mode");
        return state;
    }
    State state(State::OK, "");
    return state;
}

State People::update_loca(const int f_id, std::string& location) {
    Person& person = this->list.at(f_id);
    person.locations.emplace_back(location);
    State state(State::OK, "");
    return state;
}

State People::update_vacci(const int f_id, Vacci& vaccination) {
    Person& person = this->list.at(f_id);
    person.vaccination.emplace_back(vaccination);
    State state(State::OK, "");
    return state;
}

State People::update_nat(const int f_id, NAT& nat) {
    Person& person = this->list.at(f_id);
    person.nat = nat;
    State state(State::OK, "");
    return state;
}

State People::update_riskLevel(const int f_id, const int riskLevel) {
    Person& person = this->list.at(f_id);
    person.riskLevel = riskLevel;
    State state(State::OK, "");
    return state;
}
//-- update 函数 --//